`timescale 1ns / 1ps
module freq_meter_tb ();

  parameter SYS_CLK_NS = 10;

  reg        sys_clk;
  reg        rst_n;
  reg        sig_meas;
  reg        sig_test;
  reg        btn_sigsel;
  reg        btn_unitsel;
  wire [3:0] dt_sel;
  wire [7:0] dt_seg;
  wire       led_hz;
  wire       led_khz;
  wire       led_overflow;

  initial begin
    init_input;
    do_reset;

    do_sig_meas_test;

    do_sig_test_test;

  end

  always #(SYS_CLK_NS / 2) sys_clk = ~sys_clk;

  task init_input;
    begin
      sys_clk = 1'b0;
      rst_n = 1'b1;
      btn_sigsel = 1'b1;
      btn_unitsel = 1'b1;
      sig_meas = 1'b0;
      sig_test = 1'b0;
    end
  endtask

  task do_reset;
    begin
      @(negedge sys_clk) #1;
      rst_n = 1'b0;
      @(posedge sys_clk) #1;
      rst_n = 1'b1;
    end
  endtask

task do_sig_meas_test;
    begin
      if (freq_meter_inst.sig_sel_s == 1'b1) begin
        push_btn_sigsel;
      end
      if (freq_meter_inst.unit_sel_s == 1'b1) begin
        push_btn_unitsel;
      end
      // sig_meas 输入, 100k/200=500hz, 延迟0个clk周期
      gen_sig_meas(SYS_CLK_NS * 200, SYS_CLK_NS * 0, 2500);
      // sig_meas 输入, 100k/200=500hz, 延迟0.3个clk周期
      gen_sig_meas(SYS_CLK_NS * 200, SYS_CLK_NS * 0.3, 2500);
      // sig_meas 输入, 100k/200=500hz, 延迟0.5个clk周期
      gen_sig_meas(SYS_CLK_NS * 200, SYS_CLK_NS * 0.5, 2500);
      // sig_meas 输入, 100k/200=500hz, 延迟0.7个clk周期
      gen_sig_meas(SYS_CLK_NS * 200, SYS_CLK_NS * 0.7, 2500);
      // sig_meas 输入, 100k/300=333.3hz, 延迟0.4个clk周期
      gen_sig_meas(SYS_CLK_NS * 300, SYS_CLK_NS * 0.4, 1700);
      // sig_meas 输入, 100k/100=1khz, 延迟0.25个clk周期, 测试超量程的情况
      gen_sig_meas(SYS_CLK_NS * 100, SYS_CLK_NS * 0.25, 5000);

      // 切换量程
      push_btn_unitsel;
      // sig_meas 输入, 100k/100=1khz, 延迟0.25个clk周期
      gen_sig_meas(SYS_CLK_NS * 100, SYS_CLK_NS * 0.25, 1000);
      // sig_meas 输入, 100k/20=5khz, 延迟0个clk周期
      gen_sig_meas(SYS_CLK_NS * 20, SYS_CLK_NS * 0, 5000);
      // sig_meas 输入, 100k/20=5khz, 延迟0.3个clk周期
      gen_sig_meas(SYS_CLK_NS * 20, SYS_CLK_NS * 0.3, 5000);
      // sig_meas 输入, 100k/20=5khz, 延迟0.5个clk周期
      gen_sig_meas(SYS_CLK_NS * 20, SYS_CLK_NS * 0.5, 5000);
      // sig_meas 输入, 100k/20=5khz, 延迟0.7个clk周期
      gen_sig_meas(SYS_CLK_NS * 20, SYS_CLK_NS * 0.7, 5000);
      // sig_meas 输入, 100k/30=3.33khz, 延迟0.4个clk周期
      gen_sig_meas(SYS_CLK_NS * 30, SYS_CLK_NS * 0.4, 2000);
      // sig_meas 输入, 100k/10=10khz, 延迟0.25个clk周期, 测试超量程的情况
      gen_sig_meas(SYS_CLK_NS * 10, SYS_CLK_NS * 0.25, 10000);
    end
  endtask

  task do_sig_test_test;
    begin
      if (freq_meter_inst.sig_sel_s == 1'b0) begin
        push_btn_sigsel;
      end
      if (freq_meter_inst.unit_sel_s == 1'b1) begin
        push_btn_unitsel;
      end
      // sig_test 输入, 100k/200=500hz, 延迟0个clk周期
      gen_sig_test(SYS_CLK_NS * 200, SYS_CLK_NS * 0, 2500);
      // sig_test 输入, 100k/200=500hz, 延迟0.3个clk周期
      gen_sig_test(SYS_CLK_NS * 200, SYS_CLK_NS * 0.3, 2500);
      // sig_test 输入, 100k/200=500hz, 延迟0.5个clk周期
      gen_sig_test(SYS_CLK_NS * 200, SYS_CLK_NS * 0.5, 2500);
      // sig_test 输入, 100k/200=500hz, 延迟0.7个clk周期
      gen_sig_test(SYS_CLK_NS * 200, SYS_CLK_NS * 0.7, 2500);
      // sig_test 输入, 100k/300=333.3hz, 延迟0.4个clk周期
      gen_sig_test(SYS_CLK_NS * 300, SYS_CLK_NS * 0.4, 1700);
      // sig_test 输入, 100k/100=1khz, 延迟0.25个clk周期, 测试超量程的情况
      gen_sig_test(SYS_CLK_NS * 100, SYS_CLK_NS * 0.25, 5000);

      // 切换量程
      push_btn_unitsel;
      // sig_test 输入, 100k/100=1khz, 延迟0.25个clk周期
      gen_sig_test(SYS_CLK_NS * 100, SYS_CLK_NS * 0.25, 1500);
      // sig_test 输入, 100k/20=5khz, 延迟0个clk周期
      gen_sig_test(SYS_CLK_NS * 20, SYS_CLK_NS * 0, 5000);
      // sig_test 输入, 100k/20=5khz, 延迟0.3个clk周期
      gen_sig_test(SYS_CLK_NS * 20, SYS_CLK_NS * 0.3, 5000);
      // sig_test 输入, 100k/20=5khz, 延迟0.5个clk周期
      gen_sig_test(SYS_CLK_NS * 20, SYS_CLK_NS * 0.5, 5000);
      // sig_test 输入, 100k/20=5khz, 延迟0.7个clk周期
      gen_sig_test(SYS_CLK_NS * 20, SYS_CLK_NS * 0.7, 5000);
      // sig_test 输入, 100k/30=3.33khz, 延迟0.4个clk周期
      gen_sig_test(SYS_CLK_NS * 30, SYS_CLK_NS * 0.4, 2000);
      // sig_test 输入, 100k/10=10khz, 延迟0.25个clk周期, 测试超量程的情况
      gen_sig_test(SYS_CLK_NS * 10, SYS_CLK_NS * 0.25, 10000);
      repeat (2000) begin
        @(posedge sys_clk) #1;
      end
      sig_meas = 1'b1;
      sig_test = 1'b1;
    end
  endtask

  task gen_sig_meas;
    input integer t_period;
    input integer delay;  // 延迟时间，单位为时基数量
    input integer n_periods;
    begin : gen_sig_meas_task
      integer i;
      @(posedge sys_clk);
      #delay;
      for (i = 0; i < n_periods; i = i + 1) begin
        sig_meas = 1'b1;
        #(t_period / 2);
        sig_meas = 1'b0;
        #(t_period / 2);
      end
    end
  endtask

  task gen_sig_test;
    input integer t_period;
    input integer delay;  // 延迟时间，单位为时基数量
    input integer n_periods;
    begin : gen_sig_test_task
      integer i;
      @(posedge sys_clk);
      #delay;
      for (i = 0; i < n_periods; i = i + 1) begin
        sig_test = 1'b1;
        #(t_period / 2);
        sig_test = 1'b0;
        #(t_period / 2);
      end
    end
  endtask

  task push_btn_sigsel;
    begin
      @(negedge sys_clk) #1;
      btn_sigsel = 1'b0;
      push_btn_delay;
      @(negedge sys_clk) #1;
      btn_sigsel = 1'b1;
      push_btn_delay;
    end
  endtask

  task push_btn_unitsel;
    begin
      @(negedge sys_clk) #1;
      btn_unitsel = 1'b0;
      push_btn_delay;
      @(negedge sys_clk) #1;
      btn_unitsel = 1'b1;
      push_btn_delay;
    end
  endtask

  task push_btn_delay;
    begin
      repeat (1500) @(posedge sys_clk);
    end
  endtask

  // sys_clk 输入设置为100k，实际为100M，加速测试
  freq_meter #(
      .SYS_CLK_FREQ(100000)
  ) freq_meter_inst (
      .sys_clk(sys_clk),
      .arst_n(rst_n),
      .sig_meas_i(sig_meas),
      .sig_test_i(sig_test),
      .btn_sigsel_i(btn_sigsel),
      .btn_unitsel_i(btn_unitsel),
      .sel_o(dt_sel),
      .seg_o(dt_seg),
      .led_hz_o(led_hz),
      .led_khz_o(led_khz),
      .led_overflow_o(led_overflow)
  );

endmodule
